package com.justgame.project.service.art.aspect;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.justgame.project.cloud.base.entity.RedisZSetScore;
import com.justgame.project.cloud.common.constant.AppConstant;
import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.cloud.common.util.RedisUtils;
import com.justgame.project.service.art.entity.ArtPageInfo;
import com.justgame.project.service.art.service.IArtPageInfoService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 针对ArtPageInfo切面
 * 记录文章浏览量
 * @author ZhouWeiBo
 * @create 2022/4/12
 */
@Aspect
@Component
@Slf4j
@AllArgsConstructor
public class ArtPageInfoAspect {
    private static final String WATCH = Const.KEY_REDIS_WATCH_PAGE_COUNT;
    private static final String LIKE = Const.KEY_REDIS_LIKE_PAGE_COUNT;
    private static final String SHARE = Const.KEY_REDIS_SHARE_PAGE_COUNT;
    private static final String COMMENT = Const.KEY_REDIS_COMMENT_PAGE_COUNT;
    private final RedisUtils redisUtils;
    private final IArtPageInfoService artPageInfoService;

    @PostConstruct
    @Async("taskExecutor")
    public void init(){
        log.info("数据初始化开始...");
        int page = 1,size = 100;
        int currentRows = 0;
        do {
            //将数据库中的数据写入redis
            Page<ArtPageInfo> articleLst = artPageInfoService.page(Page.of(page,size));
            articleLst.getRecords().forEach(article -> {
                //将浏览量、点赞数和评论数写入redis
                redisUtils.zAdd(WATCH, article.getId().toString(), article.getWatchCount());
                redisUtils.zAdd(LIKE, article.getId().toString(), article.getLikeCount());
                redisUtils.zAdd(SHARE, article.getId().toString(), article.getShareCount());
            });
            /* 分页更新 */
            currentRows = articleLst.getRecords().size();
            page ++;
        }while (currentRows == 20);
        log.info("数据已写入redis...");
    }

    /**
     * 查看完详情后，就调用此方法
     */
    @Pointcut("execution(public * com.justgame.project.service.art.service.ArtPageInfoService.getPageDetail(..))")
    public void pageViewPointcut(){}

    /**
     * 关闭程序前调用
     */
    @PreDestroy
    public void afterDestroyProcess(){
        log.info("当前微服务：【{}】正在关闭！",System.getProperty(AppConstant.APPLICATION_PROPERTY));
        //将redis中的数据写入数据库
        Set<ZSetOperations.TypedTuple<Object>> viewNum = redisUtils.zReverseRangeWithScores(WATCH, 0, 10);
        writeAboutPageNum1(viewNum,WATCH);
        Set<ZSetOperations.TypedTuple<Object>> likeNum = redisUtils.zReverseRangeWithScores(LIKE, 0, 10);
        writeAboutPageNum1(likeNum,LIKE);
        Set<ZSetOperations.TypedTuple<Object>> shareNum = redisUtils.zReverseRangeWithScores(SHARE, 0, 10);
        writeAboutPageNum1(shareNum,SHARE);
        log.info("当前微服务已关闭！");
    }
    public void writeAboutPageNum1(Set<ZSetOperations.TypedTuple<Object>> numSet,String numKey){
        numSet.forEach( item -> {
            /* 获取文章id */
            Long id = (Long) item.getValue();
            /* 获取数量 */
            Long num = Objects.requireNonNull(item.getScore()).longValue();
            /* 构建更新条件 */
            ArtPageInfo dto = new ArtPageInfo();
            dto.setId(id);
            switch (numKey){
                case WATCH: dto.setWatchCount(num); break;
                case LIKE: dto.setLikeCount(num); break;
                case SHARE: dto.setShareCount(num); break;
                default:break;
            }
            artPageInfoService.updateById(dto);
        });
    }
    public void writeAboutPageNum2(List<RedisZSetScore> numSource, String numKey){
        numSource.forEach( item -> {
            /* 获取文章id */
            Long id = item.getValue();
            /* 获取数量 */
            Long num = item.getScore();
            /* 构建更新条件 */
            ArtPageInfo dto = new ArtPageInfo();
            dto.setId(id);
            switch (numKey){
                case WATCH: dto.setWatchCount(num); break;
                case LIKE: dto.setLikeCount(num); break;
                case SHARE: dto.setShareCount(num); break;
                default:break;
            }
            artPageInfoService.updateById(dto);
        });
    }

    @After("pageViewPointcut()")
    public void doViewAfter(JoinPoint joinPoint) {
        try {
            /* 获取方法执行时传入的参数 */
            Object[] objs=joinPoint.getArgs();
            Long id=(Long) objs[0];
            redisUtils.zIncrementScore(Const.KEY_REDIS_WATCH_PAGE_COUNT,id,1);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
